/**
  ******************************************************************************
  * @file    tc32l010_dma.c
  * @author  CHIPAT Application Team
  * @brief   This file provides firmware functions to manage the following
  *          functionalities of the Direct Memory Access controller (DMA):
  *           + Initialization and Configuration
  *           + Data Counter
  *           + Interrupts and flags management
  *
  @verbatim
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "tc32l010_dma.h"



/** @addtogroup XS32L010_StdPeriph_Driver
  * @{
  */

/** @addtogroup DMA
  * @brief DMA driver modules
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CCR_CLEAR_MASK   ((uint32_t)0xFFFF800F) /* DMA Channel config registers Masks */

/* DMA Channelx interrupt pending bit masks */
#define DMA_CHANNEL1_IT_MASK    ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1))
#define DMA_CHANNEL2_IT_MASK    ((uint32_t)(DMA_ISR_GIF2 | DMA_ISR_TCIF2 | DMA_ISR_HTIF2 | DMA_ISR_TEIF2))

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Deinitializes the DMAy Channelx registers to their default reset
  *         values.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and
  *         x can be 1 to 2 for DMA to select the DMA Channel.
  * @retval None
  */
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));

    /* Disable the selected DMAy Channelx */
    DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR_EN);

    /* Reset DMAy Channelx control register */
    DMAy_Channelx->CCR  = 0;

    /* Reset DMAy Channelx remaining bytes register */
    DMAy_Channelx->CNDTR = 0;

    /* Reset DMAy Channelx peripheral address register */
    DMAy_Channelx->CPAR  = 0;

    /* Reset DMAy Channelx memory address register */
    DMAy_Channelx->CMAR = 0;

    if (DMAy_Channelx == DMA_Channel1)
    {
        /* Reset interrupt pending bits for DMA Channel1 */
        DMA->IFCR |= DMA_CHANNEL1_IT_MASK;
    }
    else if (DMAy_Channelx == DMA_Channel2)
    {
        /* Reset interrupt pending bits for DMA Channel2 */
        DMA->IFCR |= DMA_CHANNEL2_IT_MASK;
    }

}

/**
  * @brief  Initializes the DMAy Channelx according to the specified parameters
  *         in the DMA_InitStruct.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel. (DMA_Channel1 or DMA_Channel2)
  * @param  DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains
  *         the configuration information for the specified DMA Channel.
  * @retval None
  */
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
{
    uint32_t tmpreg = 0;

    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
    assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR));
    assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize));
    assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc));
    assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc));
    assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize));
    assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize));
    assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode));
    assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority));
    assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M));

    /*--------------------------- DMAy Channelx CCR Configuration ----------------*/
    /* Get the DMAy_Channelx CCR value */
    tmpreg = DMAy_Channelx->CCR;

    /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
    tmpreg &= CCR_CLEAR_MASK;

    /* Configure DMAy Channelx: data transfer, data size, priority level and mode */
    /* Set DIR bit according to DMA_DIR value */
    /* Set CIRC bit according to DMA_Mode value */
    /* Set PINC bit according to DMA_PeripheralInc value */
    /* Set MINC bit according to DMA_MemoryInc value */
    /* Set PSIZE bits according to DMA_PeripheralDataSize value */
    /* Set MSIZE bits according to DMA_MemoryDataSize value */
    /* Set PL bits according to DMA_Priority value */
    /* Set the MEM2MEM bit according to DMA_M2M value */
    tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode |
              DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc |
              DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize |
              DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M;

    /* Write to DMAy Channelx CCR */
    DMAy_Channelx->CCR = tmpreg;

    /*--------------------------- DMAy Channelx CNDTR Configuration --------------*/
    /* Write to DMAy Channelx CNDTR */
    DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;

    /*--------------------------- DMAy Channelx CPAR Configuration ---------------*/
    /* Write to DMAy Channelx CPAR */
    DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr;

    /*--------------------------- DMAy Channelx CMAR Configuration ---------------*/
    /* Write to DMAy Channelx CMAR */
    DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr;
}

/**
  * @brief  Fills each DMA_InitStruct member with its default value.
  * @param  DMA_InitStruct: pointer to a DMA_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct)
{
    /*-------------- Reset DMA init structure parameters values ------------------*/
    /* Initialize the DMA_PeripheralBaseAddr member */
    DMA_InitStruct->DMA_PeripheralBaseAddr = 0;
    /* Initialize the DMA_MemoryBaseAddr member */
    DMA_InitStruct->DMA_MemoryBaseAddr = 0;
    /* Initialize the DMA_DIR member */
    DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC;
    /* Initialize the DMA_BufferSize member */
    DMA_InitStruct->DMA_BufferSize = 0;
    /* Initialize the DMA_PeripheralInc member */
    DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    /* Initialize the DMA_MemoryInc member */
    DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable;
    /* Initialize the DMA_PeripheralDataSize member */
    DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    /* Initialize the DMA_MemoryDataSize member */
    DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    /* Initialize the DMA_Mode member */
    DMA_InitStruct->DMA_Mode = DMA_Mode_Normal;
    /* Initialize the DMA_Priority member */
    DMA_InitStruct->DMA_Priority = DMA_Priority_Low;
    /* Initialize the DMA_M2M member */
    DMA_InitStruct->DMA_M2M = DMA_M2M_Disable;
}

/**
  * @brief  Enables or disables the specified DMAy Channelx.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel .
  * @param  NewState: new state of the DMAy Channelx.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected DMAy Channelx */
        DMAy_Channelx->CCR |= DMA_CCR_EN;
    }
    else
    {
        /* Disable the selected DMAy Channelx */
        DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR_EN);
    }
}

/**
  * @brief  Configure the DMAx channels remapping.
  * @param  DMAy: where y can be 1 to select the DMA peripheral.
  * @param  DMAy_CHx_RemapRequest: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel.
  * @retval None
  */
void DMA_RemapConfig(DMA_TypeDef* DMAy, uint32_t DMAy_CHx_RemapRequest)
{
    assert_param(IS_DMA_ALL_LIST(DMAy));
    assert_param(IS_DMA_REMAP(DMAy_CHx_RemapRequest));

    DMAy->CSELR &= ~((uint32_t)0x0F << (uint32_t)((DMAy_CHx_RemapRequest >> 28) * 4));
    DMAy->CSELR |= (uint32_t)(DMAy_CHx_RemapRequest & 0x0FFFFFFF);
}

/**
  * @}
  */

/**
  * @brief  Sets the number of data units in the current DMAy Channelx transfer.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel.
  * @param  DataNumber: The number of data units in the current DMAy Channelx
  *         transfer.
  * @note   This function can only be used when the DMAy_Channelx is disabled.
  * @retval None.
  */
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));

    /*--------------------------- DMAy Channelx CNDTR Configuration --------------*/
    /* Write to DMAy Channelx CNDTR */
    DMAy_Channelx->CNDTR = DataNumber;
}

/**
  * @brief  Returns the number of remaining data units in the current
  *         DMAy Channelx transfer.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel.
  * @retval The number of remaining data units in the current DMAy Channelx
  *         transfer.
  */
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
    /* Return the number of remaining data units for DMAy Channelx */
    return ((uint16_t)(DMAy_Channelx->CNDTR));
}

/**
  * @}
  */

/**
  * @brief  Enables or disables the specified DMAy Channelx interrupts.
  * @param  DMAy_Channelx: where y can be 1 to select the DMA and x can be 1 to 2
  *         for DMA to select the DMA Channel.
  * @param  DMA_IT: specifies the DMA interrupts sources to be enabled
  *         or disabled.
  *          This parameter can be any combination of the following values:
  *            @arg DMA_IT_TC: Transfer complete interrupt mask
  *            @arg DMA_IT_HT: Half transfer interrupt mask
  *            @arg DMA_IT_TE: Transfer error interrupt mask
  * @param  NewState: new state of the specified DMA interrupts.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
    assert_param(IS_DMA_CONFIG_IT(DMA_IT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected DMA interrupts */
        DMAy_Channelx->CCR |= DMA_IT;
    }
    else
    {
        /* Disable the selected DMA interrupts */
        DMAy_Channelx->CCR &= ~DMA_IT;
    }
}

/**
  * @brief  Checks whether the specified DMAy Channelx flag is set or not.
  * @param  DMA_FLAG: specifies the flag to check.
  *          This parameter can be one of the following values:
  *            @arg DMA_FLAG_GL1: DMA Channel1 global flag.
  *            @arg DMA_FLAG_TC1: DMA Channel1 transfer complete flag.
  *            @arg DMA_FLAG_HT1: DMA Channel1 half transfer flag.
  *            @arg DMA_FLAG_TE1: DMA Channel1 transfer error flag.
  *            @arg DMA_FLAG_GL2: DMA Channel2 global flag.
  *            @arg DMA_FLAG_TC2: DMA Channel2 transfer complete flag.
  *            @arg DMA_FLAG_HT2: DMA Channel2 half transfer flag.
  *            @arg DMA_FLAG_TE2: DMA Channel2 transfer error flag.
  * @note   The Global flag (DMAy_FLAG_GLx) is set whenever any of the other flags
  *         relative to the same channel is set (Transfer Complete, Half-transfer
  *         Complete or Transfer Error flags: DMAy_FLAG_TCx, DMAy_FLAG_HTx or
  *         DMAy_FLAG_TEx).
  *
  * @retval The new state of DMA_FLAG (SET or RESET).
  */
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
{
    FlagStatus bitstatus = RESET;
    uint32_t tmpreg = 0;

    /* Check the parameters */
    assert_param(IS_DMA_GET_FLAG(DMAy_FLAG));

    /* Get DMA ISR register value */
    tmpreg = DMA->ISR ;

    /* Check the status of the specified DMAy flag */
    if ((tmpreg & DMAy_FLAG) != (uint32_t)RESET)
    {
        /* DMAy_FLAG is set */
        bitstatus = SET;
    }
    else
    {
        /* DMAy_FLAG is reset */
        bitstatus = RESET;
    }

    /* Return the DMAy_FLAG status */
    return  bitstatus;
}

/**
  * @brief  Clears the DMAy Channelx's pending flags.
  * @param  DMA_FLAG: specifies the flag to clear.
  *          This parameter can be any combination (for the same DMA) of the following values:
  *            @arg DMA_FLAG_GL1: DMA Channel1 global flag.
  *            @arg DMA_FLAG_TC1: DMA Channel1 transfer complete flag.
  *            @arg DMA_FLAG_HT1: DMA Channel1 half transfer flag.
  *            @arg DMA_FLAG_TE1: DMA Channel1 transfer error flag.
  *            @arg DMA_FLAG_GL2: DMA Channel2 global flag.
  *            @arg DMA_FLAG_TC2: DMA Channel2 transfer complete flag.
  *            @arg DMA_FLAG_HT2: DMA Channel2 half transfer flag.
  *            @arg DMA_FLAG_TE2: DMA Channel2 transfer error flag.
  *
  * @note   Clearing the Global flag (DMAy_FLAG_GLx) results in clearing all other flags
  *         relative to the same channel (Transfer Complete, Half-transfer Complete and
  *         Transfer Error flags: DMAy_FLAG_TCx, DMAy_FLAG_HTx and DMAy_FLAG_TEx).
  *
  * @retval None
  */
void DMA_ClearFlag(uint32_t DMAy_FLAG)
{
    /* Check the parameters */
    assert_param(IS_DMA_CLEAR_FLAG(DMAy_FLAG));

    /* Clear the selected DMAy flags */
    DMA->IFCR = DMAy_FLAG;
}

/**
  * @brief  Checks whether the specified DMAy Channelx interrupt has occurred or not.
  * @param  DMA_IT: specifies the DMA interrupt source to check.
  *          This parameter can be one of the following values:
  *            @arg DMA_IT_GL1: DMA Channel1 global interrupt.
  *            @arg DMA_IT_TC1: DMA Channel1 transfer complete interrupt.
  *            @arg DMA_IT_HT1: DMA Channel1 half transfer interrupt.
  *            @arg DMA_IT_TE1: DMA Channel1 transfer error interrupt.
  *            @arg DMA_IT_GL2: DMA Channel2 global interrupt.
  *            @arg DMA_IT_TC2: DMA Channel2 transfer complete interrupt.
  *            @arg DMA_IT_HT2: DMA Channel2 half transfer interrupt.
  *            @arg DMA_IT_TE2: DMA Channel2 transfer error interrupt.
  * @note   The Global interrupt (DMAy_FLAG_GLx) is set whenever any of the other
  *         interrupts relative to the same channel is set (Transfer Complete,
  *         Half-transfer Complete or Transfer Error interrupts: DMAy_IT_TCx,
  *         DMAy_IT_HTx or DMAy_IT_TEx).
  *
  * @retval The new state of DMA_IT (SET or RESET).
  */
ITStatus DMA_GetITStatus(uint32_t DMAy_IT)
{
    ITStatus bitstatus = RESET;
    uint32_t tmpreg = 0;

    /* Check the parameters */
    assert_param(IS_DMA_GET_IT(DMAy_IT));

    /* Get DMA ISR register value */
    tmpreg = DMA->ISR;

    /* Check the status of the specified DMAy interrupt */
    if ((tmpreg & DMAy_IT) != (uint32_t)RESET)
    {
        /* DMAy_IT is set */
        bitstatus = SET;
    }
    else
    {
        /* DMAy_IT is reset */
        bitstatus = RESET;
    }
    /* Return the DMAy_IT status */
    return  bitstatus;
}

/**
  * @brief  Clears the DMAy Channelx's interrupt pending bits.
  * @param  DMA_IT: specifies the DMA interrupt pending bit to clear.
  *          This parameter can be any combination (for the same DMA) of the following values:
  *            @arg DMA_IT_GL1: DMA Channel1 global interrupt.
  *            @arg DMA_IT_TC1: DMA Channel1 transfer complete interrupt.
  *            @arg DMA_IT_HT1: DMA Channel1 half transfer interrupt.
  *            @arg DMA_IT_TE1: DMA Channel1 transfer error interrupt.
  *            @arg DMA_IT_GL2: DMA Channel2 global interrupt.
  *            @arg DMA_IT_TC2: DMA Channel2 transfer complete interrupt.
  *            @arg DMA_IT_HT2: DMA Channel2 half transfer interrupt.
  *            @arg DMA_IT_TE2: DMA Channel2 transfer error interrupt.
  *
  * @note   Clearing the Global interrupt (DMAy_IT_GLx) results in clearing all other
  *         interrupts relative to the same channel (Transfer Complete, Half-transfer
  *         Complete and Transfer Error interrupts: DMAy_IT_TCx, DMAy_IT_HTx and
  *         DMAy_IT_TEx).
  *
  * @retval None
  */
void DMA_ClearITPendingBit(uint32_t DMAy_IT)
{
    /* Check the parameters */
    assert_param(IS_DMA_CLEAR_IT(DMAy_IT));

    /* Clear the selected DMAy interrupt pending bits */
    DMA->IFCR = DMAy_IT;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT CHIPAT *****END OF FILE****/
